iT邦幫忙

2023 iThome 鐵人賽

DAY 25
0
自我挑戰組

chatGPT 帶你從零開始寫 websocket 連線遊戲系列 第 25

D25 遊戲開始後的 client 端頁面 (未串接連線部分)

  • 分享至 

  • xImage
  •  

之前的 client 端處理的是建立/加入房間/開始遊戲的部分,今天我們要實作的部分是遊戲開始之後的頁面和一些玩家會有的操作:玩家抽牌和玩家出牌。因為處理連線部分比較複雜,所以那個部分會推遲到明天完成。

以下就是今天的成果:

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="style.css">
  <title>簡易網頁遊戲</title>
</head>
<body>
  <div class="game-container">
    <div class="player-info">
      <h2>對手資訊</h2>
      <p>對手血量: <span id="opponent-health"></span></p>
    </div>
    <div class="player-info">
      <h2>玩家資訊</h2>
      <p>玩家血量: <span id="player-health"></span></p>
      <p>玩家手牌: <span id="player-hand"></span></p>
    </div>
    <div class="commands">
      <button onclick="updateGameInfo(gameData1)">模擬開始</button>
      <button onclick="updateGameInfo(gameData2)">模擬抽牌</button>
      <button onclick="updateGameInfo(gameData3)">模擬出牌</button>
    </div>
  </div>
  <div class="chat-container">
    <h2>聊天</h2>
    <div id="messages" class="chat-messages">
    </div>
    <div class="chat-input">
      <input type="text" id="message-input" placeholder="輸入訊息...">
      <button id="send-button">送出</button>
    </div>
  </div>
  <script src="script.js"></script>
</body>
</html>
// 初始化之後
const gameData1 = {
  playerHealth: 50,
  playerHand: [2],
  opponentHealth: 50
}

// 抽牌
const gameData2 = {
  playerHand: [2,5],
}

// 出牌
const gameData3 = {
  playerHand: [2],
  opponentHealth: 45
}

// 將遊戲資訊的 JSON 資料更新到頁面上
function updateGameInfo(gameData) {
  // 更新玩家血量
  if (gameData.playerHealth) document.getElementById("player-health").textContent = gameData.playerHealth
    
  // 更新玩家手牌數
  if (gameData.playerHand) document.getElementById("player-hand").textContent = gameData.playerHand.join(', ')
    
  // 更新對手血量
  if (gameData.opponentHealth) document.getElementById("opponent-health").textContent = gameData.opponentHealth
}

const sendMessage = () => {
  const messageInput = document.getElementById("message-input");
  const message = messageInput.value;
  if (message.trim() !== "") {
    // 顯示訊息在聊天訊息容器中
    const chatMessages = document.querySelector(".chat-messages");
    const messageElement = document.createElement("div");
    messageElement.textContent = message;
    chatMessages.appendChild(messageElement);
    chatMessages.scrollTop = chatMessages.scrollHeight;

    // 清空輸入欄位
    messageInput.value = "";
  }
}

// 處理送出按鈕的點擊事件
document.getElementById("send-button").addEventListener("click", sendMessage)
document.getElementById("message-input").addEventListener('keydown', (e) => {
  // console.log(e.code)
  if (e.code === 'Enter' || e.code === 'NumpadEnter') sendMessage()
}, false);
body {
  font-family: Arial, sans-serif;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  height: 100vh;
}
.game-container {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 800px;
  border: 1px solid #ccc;
  border-radius: 5px;
  padding: 20px;
}
.player-info {
  width: 50%;
  margin-right: 20px;
}
.chat-container {
  padding: 1rem 2rem;
  width: 50%;
}
.chat-messages {
  height: 80vh;
  overflow-y: auto;
}
.chat-input {
  width: 100%;
  display: flex;
  justify-content: space-between;
}
input[type="text"] {
  flex-grow: 1;
  padding: 5px;
  font-size: 16px;
}
button {
  padding: 5px 10px;
  font-size: 16px;
}

說明

今天實作的部分主要著重在幾個部分:

  1. 前端頁面渲染遊戲狀態
  2. 透過按鈕模擬遊戲中的事件:遊戲開始、玩家抽牌、玩家出牌
  3. 刻意省略 websocket 連線處理的部分降低實作的複雜度
  4. 刻意省略建立遊戲房間到遊戲開始的頁面轉場效果,一樣是為了降低實作複雜度

效果說明

  1. 模擬開始:遊戲初始化,頁面顯示玩家血量、對手血量、自身手牌
  2. 模擬抽牌:玩家自身手牌增加一張
  3. 模擬出牌:玩家手牌減少一張,對手血量減少

遊戲狀態的資料格式

const gameData = {
  playerHealth: 50,
  playerHand: [2],
  opponentHealth: 50
}

在前端頁面中主要使用 gameData 呈現整個遊戲狀態,這裡已經簡化到只有三個資訊

  1. 對手血量 opponentHealth
  2. 自身血量 playerHealth
  3. 自身手牌 playerHand

會設計成這樣子是為了符合「玩家的第一人稱視角」,這樣子前端的操作邏輯會比較直觀一點,相對來說,後端送過來的資料就要進行一次轉換,但這樣的成本很小是可以接受的。

另外這邊也會發現 gameData 不包含玩家牌庫、對手牌庫、對手手牌的資訊,這個是為了遊戲公平性考量。當然專案初期開發可以不用考慮到這麼多,但因為前面已經有做資料轉換的動作,就順便一起把這部分也做掉了。


上一篇
D24 遊戲開始前的資料綁定
下一篇
D26 client 從遊戲房間到遊戲開始 (包含串接連線)
系列文
chatGPT 帶你從零開始寫 websocket 連線遊戲31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
sixwings
iT邦研究生 4 級 ‧ 2023-09-26 19:42:09

已更新完實作部分

我要留言

立即登入留言